package com.zc.portal.infra.security.jwt;

import com.alibaba.fastjson.JSON;
import com.zc.commons.utils.DateTimeUtils;
import com.zc.portal.domain.dto.SysUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
@ConfigurationProperties(prefix = "protal.security.jwt")
public class SecurityJwtUtils {

    @Value("${tokenHeader}")
    public static String TOKEN_HEADER = "Authorization";
    @Value("${tokenPreffix}")
    public static String TOKEN_PREFFIX = "Bearer ";

    //**，用于signature（签名）部分解密
    private static String PRIMARY_KEY = "zhangchunjia";
    //签发者
    @Value("${iss}")
    public static String ISS = "protal";
    // 添加角色的key
    @Value("${claims}")
    public static String ROLE_CLAIMS = "authRoles";

    // 添加角色的key
    @Value("${userClaims}")
    public static String USER_CLAIMS = "userParam";

    // 过期时间是3600秒，既是1个小时
    @Value("${expiration}")
    public static final int EXPIRATION = 3600;

    // 选择了记住我之后的过期时间为7天
    @Value("${expirationRemember}")
    public static int EXPIRATION_REMEMBER = 604800;


    public static String createjwtToken(SysUser sysUser, boolean rememberMe) {
        int expiration = rememberMe ? EXPIRATION_REMEMBER : EXPIRATION;

        Set<String> roleCodes = sysUser.getAuthorities().stream().map(val -> val.getAuthority()).collect(Collectors.toSet());
        sysUser.setPassword(null);
        sysUser.setRoleList(null);
        HashMap<String, Object> map = new HashMap<>();
        map.put(USER_CLAIMS, JSON.toJSONString(sysUser));
        map.put(ROLE_CLAIMS, roleCodes);

        String jwtToken = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, PRIMARY_KEY)
                .setSubject(sysUser.getUserCode())
                .setClaims(map)
                .setIssuer(ISS)
                .setIssuedAt(new Date())
                .setExpiration(DateTimeUtils.addSeconds(new Date(), expiration))
                .compact();
        return jwtToken;
    }

    public static String getUserCode(String jwtToken) {
        return getTokenBody(jwtToken).getSubject();
    }

    public static Set<String> getRoles(String token) {
        return (Set<String>) getTokenBody(token).get(ROLE_CLAIMS);
    }

    public static Claims getTokenBody(String token) {
        return Jwts.parser()
                .setSigningKey(PRIMARY_KEY)
                .parseClaimsJws(token)
                .getBody();
    }

    @Value("${primaryKey}")
    public static void setPrimaryKey(String primaryKey) {
        PRIMARY_KEY = primaryKey;
    }
}
